import { useEffect, useRef } from 'react';
import type Fetch from '../Fetch';
import type { Options, PluginReturn } from '../index.type';
import { getCache, setCache } from '../utils/cache';
import { setCachePromise, getCachePromise } from '../utils/cachePromise';
import { trigger, subscribe } from '../utils/cacheSubscribe';
export function useCachePlugin<TData = any, TRunArgs extends any[] = any[]>(fetchInstance: Fetch<TData, TRunArgs>, options: Options<TData, TRunArgs>): PluginReturn<TData, TRunArgs> {
  const {
    cacheKey,
    cacheTime = 5 * 60 * 1000, //设置缓存数据回收时间,
    staleTime = 5 * 60 * 1000, //缓存数据被删除的时间还没到，就想重新请求数据更新缓存数据，可以理解为保鲜时间
  } = options;
  if (!cacheKey) {
    return {};
  }
  const unSubscribeRef = useRef<() => void>();
  const currentServicePromiseRef = useRef<Promise<any>>();

  useEffect(() => {
    return () => {
      unSubscribeRef.current?.();
    };
  }, []);

  function _setCache(cacheKey: string, cachedData: any) {
    setCache(cacheKey, cacheTime, cachedData);
    // 同一个 cacheKey的数据是共享的，这里更新别处的cachedData.data--fetchInstance.setState({data})，当前cachedData.data在onRequest中更新。
    trigger(cacheKey, cachedData.data);
  }

  return {
    /**
     *
     * @param service
     * @param args
     * @description const {run:run1} = useRequest(service, {cacheKye:'test1'}); const {run:run2} = useRequest(service, {cacheKye:'test1'})
     * @description run1()执行 servicePromise 和currentPromiseRef.current不存在--setCachePromise。 假如当Promise.state=== 'pending'时，run2也执行了，此时run2对应的useCachePlugin中 servicePromise存在但是currentPromiseRef.current===undefined直接return ervicePromise,
     * @description 当前run1和run2就共享了同一个Promise,当  Promise.state==='fulfilled'（也就是Promise.resolve()执行）后，当前Promise会立刻从cachePromise中删除
     * @returns
     */
    onBefore: (runArgs) => {
      const cacheData = getCache(cacheKey);

      if (cacheData && Object.hasOwnProperty.call(cacheData, 'data')) {
        if (typeof staleTime === 'number' && Date.now() - cacheData.time <= staleTime && Date.now() - cacheData.time <= cacheTime) {
          return {
            data: cacheData.data,
            loading: false,
            returnNow: true,
          };
        }
      }
    },
    onRequest: (service, runArgs) => {
      // 当前Promise.state==='fulfilled'（也就是Promise.resolve()执行）后，当前Promise会立刻从cachePromise中删除
      let currentServicePromise = getCachePromise(cacheKey);
      if (currentServicePromise && currentServicePromise !== currentServicePromiseRef.current) {
        return currentServicePromise;
      }

      currentServicePromise = service(...runArgs);
      currentServicePromiseRef.current = currentServicePromise;

      setCachePromise(cacheKey, currentServicePromise);

      return currentServicePromise;
    },
    onSuccess: (data, runArgs) => {
      if (cacheKey) {
        unSubscribeRef.current?.();
        _setCache(cacheKey, {
          data,
          runArgs,
          time: Date.now(),
        });
        // resubscribe
        // 为什么要用subscribe, 因为同一个 cacheKey的数据是共享的，必须同步更新。
        unSubscribeRef.current = subscribe(cacheKey, (d) => {
          fetchInstance.setState({ data: d });
        });
      }
    },
    onMutate: (data) => {
      if (cacheKey) {
        // cancel subscribe, avoid trigger self
        unSubscribeRef.current?.();
        _setCache(cacheKey, {
          data,
          runArgs: fetchInstance.state.runArgs,
          time: new Date().getTime(),
        });
        // resubscribe
        unSubscribeRef.current = subscribe(cacheKey, (d) => {
          fetchInstance.setState({ data: d });
        });
      }
    },
  };
}